//AP3216C.cpp
#include "AP3216C.h"
#include "XL9555.h"
#include "Wire.h"

/**
  * @brief  向ap3216c指定寄存器写入一个数据
  * @param  reg: 要写入的寄存器
  * @retval 无
  */
static void ap3216c_write_one_byte(uint8_t reg, uint8_t data)
{
    Wire.beginTransmission(AP3216C_ADDR);
    Wire.write(reg);
    Wire.write(data);
    Wire.endTransmission();
}

/**
  * @brief  在ap3216c指定寄存器读出一个数据
  * @param  reg: 要读取的寄存器
  * @retval 寄存器的值 / 0xFF:未接收到数据
  */
static uint8_t ap3216c_read_one_byte(uint8_t reg)
{
    uint8_t rd_num,rd_data;
    
    Wire.beginTransmission(AP3216C_ADDR);
    Wire.write(reg);
    Wire.endTransmission(0);    //读取标志

    Wire.requestFrom(AP3216C_ADDR, 1);
    if(Wire.available() != 0)
    {
        return Wire.read();
    }
    return 0xFF;
}

/**
  * @brief  初始化光环境传感器
  * @param  无
  * @retval true:初始化成功；false:初始化失败
 */
bool ap3216c_init(void)
{
    uint8_t temp;
    Wire.begin(IIC_SDA,IIC_SCL,400000); //初始化IIC 400KHz

    ap3216c_write_one_byte(0x00,0x04);  //复位AP3216C   软复位
    delay(20);  //复位至少10ms

    ap3216c_write_one_byte(0x00,0x03);  //模式3 ALS+PS+IR
    temp = ap3216c_read_one_byte(0x00); //读出刚刚写进去的0x03
    if(temp != 0x03)    //AP3216C 不正常
    {
        return false;
    }
    else{
        return true;
    }
}

/**
  * @brief  读取AP3216C传感器的数据
  * @note   读取原始数据,ALS,PS,IR
  *     如果同时读取这三个的模式,读取时间间隔要大于112.5ms
  *     不能在定时器中断中调用(原因未知)
  * @param  als: 数字环境光传感器(ALS) 16位数据
  * @param  ps:  接近传感器(PS) 10位数据
  * @param  ir:  红外LED(IR) 10位数据
  * @retval 无
  */
void ap3216c_read_data(uint16_t *als, uint16_t *ps, uint16_t *ir)
{
    uint8_t buf[6] = {0};
    uint8_t i;

    for(i=0; i<6; i++)
    {
        buf[i] = ap3216c_read_one_byte(0x0A+i); //读取出
    }

    if(buf[0] & 0x80)
    {
        *ir = 0;    //IR_OF位为1,则数据无效
    }
    else
    {
        //ir数据    0x0B(高8位)+0x0A(低2位)
        *ir = ((uint16_t)buf[1] << 2) | (buf[0] & 0x03);
    }
    //als数据       0x0D(高8位)+0x0C(低8位)
    *als = ((uint16_t)buf[3] << 8) | buf[2];

    if(buf[4] & 0x40)
    {
        *ps = 0;    //PS_OF位为1,则数据无效
    }
    else
    {
        //ps数据    0x0F(高6位)+0x0E(低4位)
        *ps = ((uint16_t)(buf[5] & 0x3F) << 4) | (buf[4] & 0x0F);
    }
}

// ============== 中断相关函数实现 ============== //


/**
  * @brief  设置中断清除模式
  * @param  mode: 清除模式 (AUTO_CLEAR 或 MANUAL_CLEAR)
  * @retval 无
  */
void ap3216c_set_int_clear_mode(CLEAR_TYPE mode) {
    // 0x02寄存器: INT Clear Manner
    // bit0: 0 = 自动清除 (读数据寄存器清除)
    //        1 = 手动清除 (写状态寄存器清除)
    ap3216c_write_one_byte(0x02, mode);
}


/**
  * @brief  初始化中断功能 启动读取后自动清除
  * @param  int_types: 中断类型 (ALS_INT 和/或 PS_INT)
  * @note   中断引脚触发拉低,默认为读取后自动拉高清除中断
  *     中断引脚在扩展芯片上 xl9555_get_pin(AP_INT)
  * @retval 无
  */
void ap3216c_init_interrupt(INT_TYPE int_types) {
    xl9555_init();
    xl9555_io_config(AP_INT,IO_SET_INPUT);  //在IO扩展芯片上

    //默认的中断清除方式为自动清除(0x02寄存器)
    //ap3216c_write_one_byte(0x02, 0x00);
    
    // 配置ALS中断持久性(默认1次, 0x10寄存器)
    if(int_types & ALS_INT) {
        ap3216c_write_one_byte(0x10, 0x00);  // 默认设置
    }
    
    // 配置PS中断持久性和模式(0x20和0x22寄存器)
    if(int_types & PS_INT) {
        ap3216c_write_one_byte(0x20, 0x05);  // 默认设置: 增益x2, 持久性2次
        ap3216c_write_one_byte(0x22, 0x01);  // 滞回模式(默认)
    }
}

/**
  * @brief  设置ALS阈值
  * @param  low: 低阈值 (16位) 0~1023
  * @param  high: 高阈值 (16位) 0~1023
  * @retval 无
  */
void ap3216c_set_als_threshold(uint16_t low, uint16_t high) {
    // 设置低阈值 (0x1A-0x1B)
    ap3216c_write_one_byte(0x1A, low & 0xFF);        // 低字节
    ap3216c_write_one_byte(0x1B, (low >> 8) & 0xFF); // 高字节
    
    // 设置高阈值 (0x1C-0x1D)
    ap3216c_write_one_byte(0x1C, high & 0xFF);       // 低字节
    ap3216c_write_one_byte(0x1D, (high >> 8) & 0xFF);// 高字节
}

/**
  * @brief  设置PS阈值
  * @param  low: 低阈值 (10位) 0~1023
  * @param  high: 高阈值 (10位) 0~1023
  * @retval 无
  */
void ap3216c_set_ps_threshold(uint16_t low, uint16_t high) {
    // PS阈值是10位数据 (0-1023)
    low &= 0x3FF;
    high &= 0x3FF;
    
    // 设置低阈值 (0x2A-0x2B)
    ap3216c_write_one_byte(0x2A, low & 0x03);        // 最低2位
    ap3216c_write_one_byte(0x2B, (low >> 2) & 0xFF); // 高8位
    
    // 设置高阈值 (0x2C-0x2D)
    ap3216c_write_one_byte(0x2C, high & 0x03);       // 最低2位
    ap3216c_write_one_byte(0x2D, (high >> 2) & 0xFF);// 高8位
}

/**
  * @brief  清除中断标志
  * @param  int_type: 中断类型 (ALS_INT 或 PS_INT)
  * @retval 无
  */
void ap3216c_clear_interrupt(uint8_t int_type) {
    // 手动清除方式: 向0x01寄存器写入中断类型
    ap3216c_write_one_byte(0x01, int_type);
}
